هناك عوالم اخرى لتوضيح مفهوم الكائنات والأصناف .فالأصناف classes بطبعتها هي مسودات من الكائنات ، والكائن حالات من الأصناف . بمعنى اخر تقع الاشياء في تصنيفات Categories مثل الكمبيوتر والسيارات والأشجار ، وغالبا ما يتم الإشارة إلى هذة التصنيفات بأسم الاصناف Classes فالصنف هو تصنيف أو مجموعة من الأشياء التى لها سمات متشابهة Similar attributes وتصرفات شائعة عامة common behaviors ، الكائن هو تواجد instance من الصنف أو شيء خاص له قيم معينة من السمات والتصرف .
النموذج Model هو تجريد موقف مما يسهل عملية تصور البرنامج ويسهل صيانتة كما انة في حالة الرجوع لهذة المخططات الرسومية (النماذج) بعد فترة يسهل فهم البرنامج وهكذا مجرد abstract عندما يكون له صفات ليس لغيرة من هذة الصفات (السؤال الان غالباً التجريد لله سبحانة تجردت صفاتة وكاملة) ، بطبيعة الحال تتكون النماذج من كائنات Objects له حياة Alive تعرف سماتها التي تتسم بها عن باقي الاصناف . ويمكنها عمل الأشياء باستخدام طرقها Methods وتتواجد في حالات مختلفة Different states ، وكل كائن هو فريد unique وليس لأي كائن آخر فمثلاُ تعيش الكائنات في العالم كما تعيش في الاتصالات فهي تتبادل الرسائل مع بعضها البعض ولها علاقات Relationships مع بعضها البعض .
تدعم لغة البيرل برمج الكائنات الموجهه وتقدم الميزات كإي لغة اخرى توفر OOP وقد تم تطويرها بسبب صعوبات كثيرة في اساليب البرمجة التقليدية ، ففي البرامج الصغيرة لاتدعو الحاجة لإي مبدأ تنظيمي فالمبرمج ينشأ لائحة من التعليمات ويقوم الجهاز بتنفيذها لكن عندما تصبح البرامج اكبر مع امتداد الوحـدات البرمجية لايعود الكود فعالأ جداً ، وبإمكان القليل من المبرمجين فهم برنامج يتألف من بضع مائات من الاسطر الإ اذا كانت مقسمة إلى اجزاء أصغر حجماً ، البيرل لم تكن اصلاً مصممة للبرمجة الكائنات الموجهه فمن الميزات المكتسبة من الاصدار الخامس ( المراجع الرمزية و الحزم ) اكتسبت هذة الميزة على الرغم من هذا فأن البيرل قوية للبرمجه الموجهه ولديها صرامة وتعارض مع اللغات الاخرى وكذلك اللغات لديها صرامة كالجافا مثلاً التي تطلب بأن كل شيء لابد ان يكون لدية كائن حتي في البرنامج الرئيسي main ، كذلك البيرل لها وجهه نظر لعمل التؤارث وكيف تعمل المتغيرات او الطرق سواء خاصة private او عامة public وكيفية انشاء الكائن وكيفية اضافة تحميل الزائد وفي هذا القسم سوف نناقش الاساسيات ولنبدأ هنا بالثلاث القواعد الاساسية :
الصنف class هي package ، التي هي من مجموعة من المتغيرات والدوال
الطرق methods هي الدوال المعرفة في الحزمة
الكائن object هو مرجع لتلك البيانات في الصنف
package Bug; # انشاء صنف
use strict;
sub new # انشاء باني داخل الصنف
{
my ($class) = @_;
my $objref = {};
.
.
bless $objref, $cla # لإنشاء كائن ، عمل بلاس للمرجع
}
sub print_me # انشاء الطريقة داخل الصنف
{
my ($self) = @_;
print "print_me\n";
.
.
}الدالة bless()
تاخذ الدالة bless وسيطين وهما المرجع الى متغير ويحوي على اسم تلك الصنف
الصيغة:
bless REF,CLASSNAME bless REF
REF هو مرجع الى كائن عند عمل blessing إلية عن طريق إستدعاء الدالة bless ،ويصبح الان كائن في حزمة CLASSNAME ، في حالة حذف وسيط CLASSNAME تستخدم الدالة الحزمة الحالية ، وفي اغلب الاوقات تستخدم مع وسيطين لعمل blessing لصنف متوارثة ، وفي حالتة استدعاء الدالة للصنف المحددة يتم وضعها في الباني new وذلك لإعادة مرجع إلى كائن إلى البرنامج الرئيسي في كل أستدعاء للباني ، لتؤضيح ذلك المثال التالي يصور آليات عمل الدالة
sub print_me
{
my ($self) = @_;
print "print_me\n";
}
$hashref = { first_name =>'Jane', last_name => 'Doe' };
$object=bless $hashref;
print $object,"\t",$hashref;
print $object->{last_name};
$object->print_me(@args); #same: $hashref->print_me(@args);
لاشيء يحدث في تركيب المتغير $hashref ومازال مرجع هاش ومازال يمكن عمل له dereference او اضافة او وصول او حذف المدخلات في الهاش ومازال بنفس القيم والفهارس ، لكنه حالياً اصبح مرجع بمعرفة الحزمة التي تعود إليها ، واذا حاولنا استدعاء الطريقة علية سوف تنظر البيرل في الحزمة لكي يعرف على تلك الطريقة
وهنا الاختلافات بين أشكال الوصول لتميز بين الطرق المختلفة فيما سبق
$hsh_ref->{"key"};# Access the hash referred to by $hashref
$arr_ref->[$index];# Access the array referred to by $arrayref
$sub_ref->(@args);# Access the sub referred to by $subref
$obj_ref->method(@args);# Access the object referred to by $objref
هو الاجزء المهم لإنشاء كائن جديد من الصنف ،فعلى سبيل المثال لإنشاء باني في البيرل للإعادة مرجع التركيب الى أن يصبح blessed الى صنف Class.pm
#Class.pm
package My::Object::Class;
use strict;
sub new {
my $this = {}; # create a reference to a hash
bless $this; # mark reference as object of this class
return $this; # return it.
}فالـ {} constructs هو مرجع هاش مخفي فارغ والقيمة العائدة الى هذا الهاش تخصص الى المتغير المحلي this ،والدالة bless تأخذ ذلك المرجع لإنشاء مرجع كائن لتلك الصنف ، وتعيد مرجع الكائن الى البرنامج الرئيسي بالتعلمية returns ، فالقيمة العادة من استدعاء الطريقة new تشير الى هذا الهاش المخفي وعند الخروج من الطريقة new فسوف يحرر المرجع this من الذاكرة ، لكن باستدعاء الطريقة تحفظ المرجع الى هذا الهاش ، لذا count المرجع الى الهاش لايكون بالصفر فالبيرل تحفظ الهاش في الذاكرة (يعرف في البيرل بالـ Closures )
لإنشاء الكائن في البرنامج الرئيسي نستدعي بواسطة new :
$object = new My::Object::Class;
واكثر وضوحاً من خلال
$object = My::Object::Class->new(); $object = My::Object::Class::new();
ان مشكلة الباني لايمكن ان يعالج التؤريث ، ربما يتم استدعاء الباني من صنف فرعي subclass ، في هذة الحالة فأن الصنف تكون blessed الى الصنف الفرعي الذي يرثة، بتعريف الباني في الصنف الفرعي ، لذلك لكتابتة بشكل صحيح نستخدم وسيطين الى الدالة bless عند التؤارث:
sub new {
my $class = shift;
my $this = {};
bless $this, $class;
return $this;
}التي تساوي العبارة التالية بنفس العمل
sub new {
return bless {}, shift;
}في نفس الصنف يمكن اعطاء قيم او استدعاء طريقة
# card1.pm
package Game::Card;
use strict;
sub new {
my ($class, $name, $suit) = @_;
my $this = bless {}, $class;
$this->{name} = $name;
$this->{suit} = $suit;
return $this;
}
1;وبإمكان كتابة هادم للصنف نفسها ، وبعكس الباني سيهتم عادة بإلغاء تخصيص مساحة الذاكرة التي كان الباني قد خصصها للكائن ،حتى بعدم كتابة الهادم يزود المفسر بروتين خاص لإلغاء تخصيص الذاكرة التي كان يحتلها الكائن تلقائياً الخروج من البرنامج كما في خوازميات وبرمجيات لغة الجافا لإزالة النفايات Garbage collection
#Class.pm
package My::Object::Class;
use strict;
sub new {
print "iam the constructor.\n";
my $this = {}; # create a reference to a hash
bless $this; # mark reference as object of this class
return $this; # return it.
}
sub DESTROY {
print "iam the destructor.\n";
}
1;في المثال السابق لايقوم الباني بإي تخصيص لكنه يقوم بإنشاء مرجع للكائن ويعرض الرسائلة ،كذلك الهادم لاينفذ اي امر سواء يعرض رسائلة، نلاحظ ان الهادم يكتب باحرف الكبيرة ويمكن ازالة الكلمة المحجوزة sub ، وهنا البرنامج الرئيسي
use strict;
use lib '/home/tisdall/MasteringPerlBio/development/lib';
use Class;
print "starting program...\n";
my $object1 = My::Object::Class->new();
my $object2 = My::Object::Class->new();
{
my $object3 = My::Object::Class->new();
} #call Destructor
print "ending program...\n";نلاحظ انة لايوجد استدعاء للهادم وعند انتهاء البرنامج الرئيسي بالوصول الى القوس او البلوك ينتهي مدى الكائنات ويتم تدميرها تلقائياً حيث يتم استدعاء هادم كل كائن قبل تدميره كما يستدل من الخرج
starting program... iam the constructor. iam the constructor. iam the constructor. iam the destructor. ending program... iam the destructor. iam the destructor.
نستطيع امرار وسطاء من خلال الباني فعلى سبيل المثال وحدة Gene1
package Gene1;
use strict;
use warnings;
use Carp;
sub new {
my ($class, %arg) = @_;
my $this={
_name => $arg{name} || croak("no name"),
_organism => $arg{organism} || croak("no organism"),
_chromosome => $arg{chromosome} || "????",
_pdbref => $arg{pdbref} || "????",
};
bless $this, $class;
return $this;
}
sub name { $_[0] -> {_name} }
sub organism { $_[0] -> {_organism} }
sub chromosome { $_[0] -> {_chromosome}}
sub pdbref { $_[0] -> {_pdbref} }
1;وتعليمات البرنامج المسمى testGene1
# testGene1.pl
use strict;
use warnings;
use lib "/home/tisdall/MasteringPerlBio/development/lib";
use Gene1;
print "Object 1:\n\n";
my $obj1 = Gene1->new(
name => "Aging",
organism => "Homo sapiens",
chromosome => "23",
pdbref => "pdb9999.ent"
);
print $obj1->name, "\n";
print $obj1->organism, "\n";
print $obj1->chromosome, "\n";
print $obj1->pdbref, "\n";
print "Object 2:\n\n";
my $obj2 = Gene1->new(
organism => "Homo sapiens",
name => "BACK",
);
print $obj2->name, "\n";
print $obj2->organism, "\n";
print $obj2->chromosome, "\n";
print $obj2->pdbref, "\n";
print "Object 3:\n\n";
my $obj3 = Gene1->new(
organism => "Homo sapiens",
chromosome => "23",
pdbref => "pdb9999.ent"
);
print $obj3->name, "\n";
print $obj3->organism, "\n";
print $obj3->chromosome, "\n";
print $obj3->pdbref, "\n";
شرح البرنامج :
Carp هي وحدة برمجية قياسية لديها اربع دوال لإعطى معلومات عن رسائل الخطأ وتحذيرات في حالة وجود مشاكل ،فالدالة carp تطبع رسائلة تحذير بينما الدالة croak تطبع رسائلة خطأ ثم الخروج من البرنامج وهي مفيدة عند التطوير فهي تطبع اسم الملف ورقم السطر فعلى سبيل المثال اختبر
my $obj1 = Gene1->new(
organism => "Homo sapiens",
chromosome => "23",
pdbref => "pdb9999.ent"
); سوف يظهر الخطأ ثم الخروج
no name at testGene1 line 9
لعرض معلومات الامر perldoc Carp من نافذة الاوامر
NAME carp - warn of errors (from perspective of caller) cluck - warn of errors with stack backtrace (not exported by default) croak - die of errors (from perspective of caller) confess - die of errors with stack backtrace
يمكن اختصار الباني بنفس التاثير
sub new {
my ($class, %arg) = @_;
return bless {
_name => $arg{name} || croak("no name"),
_organism => $arg{organism} || croak("no organism"),
_chromosome => $arg{chromosome} || "????",
_pdbref => $arg{pdbref} || "????",
}, $class;
}الطريقة new تمرر وسطاء الهاش في ملف testGene1 وبشكل آلي تعبر الى الباني new واول وسيط تخصص الى المتغير $class باسم الحزمة الحالية ثم باقي الوسطاء تخصص الى %arg ثم تعيد مرجع الهاش باسم الصنف Gene1=HASH(0x235344) الى متغير البرنامج $obj1
بدانا بتعريف attributes (_name, _organism, _chromosome, and _pdbref ) في الصنف التي سوف تستعمل بشكل داخلي او خاص للكائن الصنف ، فعند إستخدام الكائن في البرنامج testGene1 لايجب علينا معرفة اسماء الهاش حيث ان التأثر من خلال الوسطاء المحددة في الصنف للقيم التي تعطى الى هذة attributes كالـ $arg{name}..الى غير ذلك ، وايضاُ من خلال الدوال المسمى name,..الى غير التي تعيد قيمة attributes المخزن في صنف الكائن
الشرطة التحتية امام الاسم متفق علية من قبل المبرمجين تشير الى ان العنصر في موضع السؤال اما متغير او مفتاح الهاش (فقط اتفاقية للجعل الكود اسهل للقراءة والفهم )وتعني للإستعمال الداخلي وليس خارج الوحدة وتسمى "private" بالتالي الوصول إليها من داخل الصنف ولايمكن الوصول إليها من خارج الصنف ، ففي المثال السابق نلاحظ ان البيرل على خلاف قيود الـ OO للغات الاخرى يمكن الوصول للبيانات الخاصة بوصول غير مباشر باستخدام الصنف ، فالمفسر يستدعى الطريقة في الكائن $obj1->name والتي تحمل الوسطاء @_ واول وسيط لها هو الكائن $_[0] ، ثم بعد ذلك الوصول الى قيمة الهاش المخفي في الصنف وطباعة القيمة
Object 1: Aging Homo sapiens 23 pdb9999.ent Object 2: BACK Homo sapiens ???? ???? Object 3: no name at testGene line 35
تؤفر البيرل تقنية مفيده فإذا حاولنا في الشكل العادي استدعى دالة غير موجودة سوف يعطي المفسر البيرل خطأ ولا تستطيع عمل اي شيء ويجب علينا تعرف الدالة قبل تشغيل عملية التجميع ، يمنح مفسر البيرل الدالة AUTOLOAD باستدعى دالة غير موجودة واستدعاء الدالة AUTOLOAD التي تعيق عملية التجميع عند التعامل مع الاستدعاءات الغير موجودة ، وعند إدراج الدالة AUTOLOAD في الحزمة تشحن الموديل AutoLoader.pm من مكتبة البيرل
package Robot;
sub AUTOLOAD
{
print"Sorry $AUTOLOAD isn't defined.\n";
}فالدالة AUTOLOAD سوف تقوم بامسك او اعتراض اي استدعاء غير موجود في الحزمة واستلام اسم الدالة في المتغير الحزمة الخاص $AUTOLOAD ، وعند تمرير وسطاء من خلال الدالة
#!/usr/bin/perl
# autoload.pl
use warnings;
use strict;
sub AUTOLOAD {
our $AUTOLOAD; # "use vars '$AUTOLOAD'" for Perl < 5.6
$" = ',';
print "You called '$AUTOLOAD(@_)'\n";
}
fee('fie','foe','fum');
testing(1,2,3);
ففي البداية اعلان عن المتغير الحزمة $AUTOLOAD باستعمال الكلمة المحجوزة our التي سوف تعرف اسم مستعار مؤقتة temporary alias
You called 'main::fee(fie,foe,fum)' You called 'main::testing(1,2,3)'
فهناك العديد من الوحـدات في المكتبة القياسية تفيد autoloading لزيادة سرعه البرنامج كوحدة autouse التي تقوم بتاخير تجميع الدوال حتي تستدعئ ، وتؤخرعموماً شحن كل الوحدات حتي تستدعى احدى دوالها ،على اي حال فهي ليس محببة فعندما تشحن جميع الوحـدات فهي تشحن مرة واحدة ، ايضاً هناك الوحدة AutoSplit و AutoLoader لحل هذة المشكلة ، فالـ AutoSplit يقسم ملف الوحدة الى دوال منفصلة والتي سوف تقوم بقراءتها AutoLoader بعد ذلك حيث تجمع لحظة طلب او استدعى دالة معينة ،فمثل هذة الوحدات تستعمل نموذجياً اثناء توزيع وتنزيل الوحدة ولفك الدول من السورس الاصل بواسطة AutoSplit بعملية يدوية ،ايضاً الـSelfLoader تفعل بشكل اسهل للاحل فهي تسمح لنا بتخزين الكود كنص text داخل ملف الوحدة وتجمعه عند الحاجة الية بينما هي ليست كفوءاً كالـ AutoLoader التي لاتشحن كود الدالة اذا لم تحتاجها ، وهي لاتحتاج اي اضافات للعمل .
عند إستخدام الكلمة المحجوزة use ليس هناك إي تعقيد لإستيراد الواحـدات او إستيراد المتغيرات واسماء الدوال ، فهي جميعها مستندة على إستدعاء الدالة import في وقت التجميع وليس هناك ضرورة ان نقوم بتصدير اي شيء لدالة import ، فنادراً ماتصدر وحدات الكائنات الموجهه هذة الـsymbols (الدوال ، التعريفات ، المتغيرات ) التي تستولي عادتاً على آلية الإستيراد بدلاًُ من عمل اعداءات لبيانات صنف الوحدة، التوجهه use تقوم بالاستدعاء import بشكل آلي لتلك الوحدة لإنشاء الحزمة من نفس الاسم ، والطريقة import سوف تبحث عن الحزمة باسم الوحدة ، بغض النظر عن شحن محتويات الوحدة .
ان الفائدة الرئيسية من استخدام use على require هو مفهوم الإستيراد ، لكن يمكننا ان نقوم بعمل إستيراد بنفسنا باستدعى الطريقة import من موديل الكائن الموجهه OOmodule لإستيراد كل المتغيرات والدوال
BEGIN {
require Module;
Module->import; # or 'import Module'
}لكن الأسهل والمناسب أن نستخدم use فأن نفذت الكلمة use مع أسم الوحدة البرمجية فقط فلان يمر اي وسيط الى الدالة import وسوف يستخدم الأفتراضي لهذا الحدث ولان يتأثر لعمل شيء ويسبب إلى إستيراد المجموعة الافتراضية من الـ symbols لإستخدمنا ، بينما وحـدات الكائنات الموجهه لان يتجه الى إستيراد اي شيء منذ ان توقعنا الى استعملهم بواسطة أستدعاء الطريقة ، وان كانت الوحدة لاتنجز الطريقة import لان يحدث شيء بالطبع ، وذلك يعني أن طرق OOmodules تستورد بالأفتراضي أو بواسطة تحديد القائمة والمطلوب استيرادها ونسطيع ادرجها اما بالاقواس او بإستخدام المعامل qw
# importing a list of symbols with a comma-separated list:
use Module ('sub1', 'sub2', '$scalar', '@list', ':tagname');
# it is more legible to use 'qw':
use Module qw(sub1 sub2 $scalar @list :tagname);
# a single symbol can be specified as a simple string:
use Module 'sub1';
# if strict references are not enabled, a bareword can be used:
use strict refs;عادتاً تقوم الوحـدات البرمجية الوظفية functional modules بتصدير symbols من الوحدة بواسطة وحدة Exporter ، لكي تحدد ما الذي يسمح لنا باستيرادة أو ما الذي سوف نحتاج لإستيرادة فقط ، في المثال السابق فقد تكون Symbols أسماء دوال أو متغيرات أو تاج tags الذي يتقدم بواسطة الرمز : أن دعمت ذلك في الوحدة ،فمثلاً كما سبق بلوك BEGIN نحتاجها لإعطاء قيم ابتدئية قبل الاستخدم ، ولتقدير قائمة من المتغيرات وتصديرها في وقت التجميع إي قبل ان يتم تجميع الوحدة واستعمالها في الكود
package test;
use strict;
BEGIN {
use vars '@SYMBOLS';
for (0..5)
{
$SYMBOLS[$_]=$_;
}}
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = (@SYMBOLS);
use warnings; use strict; use lib "/home/tisdall/MasteringPerlBio/development/lib"; use test; print @test::SYMBOLS;
الحزمة بالصيغة الصحيحة مع ذلك سوف تحصل على رسائلة خطأ اثناء التجميع ويظهر بأن المصفوفة (او الطرق او متغير) غير موجودة ، فهذا الخطأ يحدث بسبب ان المصفوفة غير مصدرةويجب تصدير هذة المتغيرات ،ولتصدير نضمن وحدة Exporter بإضافة الى التالي في بداية الحزمة :
use Exporter; @ISA = qw(Exporter);
وضعنا المصفوفة @ISA مع اسم الصنف Exporter للبحث عنها ، ثم تدرج الـsymbol مع المصفوفة @EXPORT ، على سبيل المثال لتصدير اكثر من طريقة المسمى closeMain و declareMain نستعمل التالي :
@EXPORT(declareMain, closeMain);
الؤراثة في لغة البيرل تعتمد بشكل اساسي على الصنف المتضمنة في المصفوفة الخاصة @ISA فالبيرل تعاملها كمصفوفة خاصة لاسماء االأصناف، وهي شبية الى حد ما بالمصفوفة @INC حيث تحتوي على المجلدات المراد البحث عن الملفات فيها ،اما المصفوفة @ISA تحتوي على اسماء الأصناف( classes ) لتبحث عن الطرق في الصنف( تحتوي فيها أصناف base ) في الحزمة الحالية التي تؤرث منها فأن كانت طرق صنف الـbase غير معرف في المصفوفة الخاصة @ISA فأن البيرل سوف تبحث عن الدالة AUTOLOAD في الصنف المؤرثة ثم في صنف الـbase ، وان الدالة AUTOLOAD غير موجودة سيبحث المفسر في الصنفUNIVERSAL.pm التي تمسك بكل الطرق الغير معرفة في اي مكان اخر ، عموماً البيرل بعد ذلك تولد الخطأ والاستعلام للمعالجته .
package BaseClass;
use strict;
sub new {
my $class = shift;
my $this = {};
$this->{'BASE'} = 'Colombian';
bless $this, $class;
return $this;
}
# This subroutine sets the class name
sub setBaseClass{
my ($self, $name) = @_;
$self->{'BASE'} = $name;
print "Set Base to $name \n";
}
1;
package SubClass;
use strict;
use BaseClass;
our @ISA = qw(BaseClass);
sub new {
my $class = shift;
my $this = BaseClass->new(); # انشاء كائن من صنف BaseClass #
$this->{'SUB'} = 'Instant'; # unless told otherwise
bless $this, $class; #انشاء مرجع الى كائن للصنف الحالي
return $this;
}
sub setSubClass{
my ($self,$name) = @_;
$self->{'SUB'} = $name;
print "Set SubClass type to $name \n";
}
1;
#!/usr/bin/perl
use strict;
use SubClass;
my $cup = new SubClass;
print "\n --------------- Initial values ------------ \n";
print "SubClass: $cup->{'SUB'} \n";
print "Baseclass: $cup->{'BASE'} \n";
print "\n --------------- Change BaseClass ---------- \n";
$cup->setBaseClass('Mixed');
print "BaseClass is now: $cup->{'BASE'} \n";
print "\n --------------- Change SubClass ---------- \n";
$cup->setSubClass('Instant');
print "SubClass is now: $cup->{'SUB'} \n";
--------------- Initial values ------------ SubClass: Instant Baseclass: Colombian --------------- Change BaseClass ---------- Set Base to Mixed BaseClass is now: Mixed --------------- Change SubClass ---------- Set SubClass type to Instant SubClass is now: Instant
no شكل معاكس للتوجية use ، والتي لان تقوم بإستيراد الميزة المحددة بواسطة استدعاء الدالة unimport وبامكان عدم إستيراد قائمة بنفس صيغة use
no Module qw(symbol1 symbol2 :tagname);
وهي تكافي
BEGIN {
require Module;
unimport('symbol1', 'symbol2', ':tagname');
}التوجية no على خلاف التوجيه use ، فبعدم كتابة الدالة unimport سوف يحدث خطأ fatal ، بينما عدم كتابة import تخبر بإستخدام الوحدة لكن عدم إستيراد اي شيء وهي تكافئ مايسمى بالطمس suppress
use Module(); # suppress all imports
#مساوي
BEGIN { require Module; }